package com.frame.database.session;

import java.io.BufferedReader;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.orm.hibernate4.SessionFactoryUtils;

import com.frame.database.*;
import com.frame.database.dataconver.DataConversionFactory;
import com.frame.database.operate.Jsession;
import com.frame.database.util.Seq;
import com.frame.hibernate.HibernateUtil;
import com.frame.util.BeanUtils;
import com.frame.util.StreamUtils;
import com.wframe.framework.database.BaseDao;
import com.wframe.framework.spring.SpringContextHolder;

/**
 * @Title: 系统
 * @Description:
 * @Copyright: Copyright (c) 2012
 * @Company:
 * @author 王海锋
 * @CreatedTime:2012-6-10 上午10:48:26
 * @version 1.0
 */

public class JdbcSession implements Jsession{

    private List<PreparedStatement> preparedStatementList;
    private List<Statement> statementList;
    private List<ResultSet> resultSetList;
    private String ftg;
    private boolean loadLob=false;
    private Connection conn;
    private BaseDao baseDao=new BaseDao();

    public JdbcSession(){
        baseDao.setSessionFactory((SessionFactory)SpringContextHolder.getBean("sessionFactory"));
        baseDao.setJdbcTemplate((JdbcTemplate)SpringContextHolder.getBean("jdbcTemplate"));
    }
    public JdbcSession(String ftg){
        this.ftg=ftg;
        baseDao.setSessionFactory((SessionFactory)SpringContextHolder.getBean("sessionFactory"));
        baseDao.setJdbcTemplate((JdbcTemplate)SpringContextHolder.getBean("jdbcTemplate"));
    }
    public List<JdataBean> query2(String sql,List parmList) throws Exception{
        Object[] obj=null;
        if(parmList!=null){
            obj=new Object[parmList.size()];
            for(int i=0;i<parmList.size();i++)
                obj[i]=parmList.get(i);
        }
        return query(sql, obj);
    }
    public List<JdataBean> query(String sql,Object[] parmObj) throws Exception{
        return baseDao.querySql(sql, parmObj);
    }
    @Override
    public List<Map> queryMap(String sql,Object[] parmObj){
        return baseDao.querySqlMap(sql, parmObj);
    }
    public List<JdataBean> query2(String sql,List parmList,Class dataVoclass) throws Exception{
        Object[] obj=null;
        if(parmList!=null){
            obj=new Object[parmList.size()];
            for(int i=0;i<parmList.size();i++)
                obj[i]=parmList.get(i);
        }
        return query(sql, obj,dataVoclass);
    }
    public List query(String sql,Object[] parmObj,Class dataVoclass) throws Exception{
        List<JdataBean> list=query(sql, parmObj);
        List resultList=new ArrayList();
        resolveDataToClass(list,resultList,dataVoclass);
        return resultList;
    }
    public PageResult query2(String sql,List parmList,int size,int pageNo,Class dataVoclass) throws Exception{
        Object[] obj=null;
        if(parmList!=null){
            obj=new Object[parmList.size()];
            for(int i=0;i<parmList.size();i++)
                obj[i]=parmList.get(i);
        }
        return query(sql, obj,size,pageNo,dataVoclass);
    }
    public PageResult query(String sql,Object[] parmObj,int size,int pageNo,Class dataVoclass) throws Exception{
        return null;
    }
    private void resolveDataToClass(List<JdataBean> rs,List resultList,Class dataVoclass) throws Exception{
        Method[] methods=dataVoclass.getMethods();
        for(JdataBean data:rs){
            Object bean = dataVoclass.newInstance();
            Object[] keys=data.getDataMap().keySet().toArray();
            for (int i=0;i<keys.length;i++){
                String colname=keys[i].toString();
                for(int f=0;f<methods.length;f++){
                    String m=methods[f].getName();
                    if(m.startsWith("set")){
                        m=m.replace("set", "");
                        if(colname.equalsIgnoreCase(m)){
                            try{
                                Object obj=data.get(colname);
                                Object value=obj;
                                if(isLoadLob()){

                                }
                                BeanUtils.setValue(bean, m, value,methods[f].getParameterTypes()[0]);
                            }catch(Exception e){}
                            break;
                        }
                    }
                }
            }
            resultList.add(bean);
        }
    }

    public PageResult query2(String sql,List parmList,int size,int pageNo) throws Exception{
        Object[] obj=null;
        if(parmList!=null){
            obj=new Object[parmList.size()];
            for(int i=0;i<parmList.size();i++)
                obj[i]=parmList.get(i);
        }
        return query(sql, obj,size,pageNo);
    }
    public PageResult query(String sql,Object[] parmObj,int size,int pageNo) throws Exception{
        return baseDao.querySql(sql, parmObj, size, pageNo);
    }
    public TableBean getBean(Class classes,Serializable key) throws Exception{
        return null;
    }
    public JdataBean getObject(String sql,Object[] obj) throws Exception{
        List<JdataBean> list=query(sql, obj);
        if(list.size()>0)
            return list.get(0);
        else
            return null;
    }

    public JdataBean getObject2(String sql,List parmList) throws Exception{
        Object[] objs=null;
        if(parmList!=null){
            objs=new Object[parmList.size()];
            for(int i=0;i<parmList.size();i++)
                objs[i]=parmList.get(i);
        }
        return getObject(sql,objs);
    }

    public void save(TableBean bean) throws Exception{
        Field[] field=bean.getClass().getDeclaredFields();
        TableKey key=bean.getTableKey();
        if(key.getTableName()==null || "".equals(key.getTableName()))
            throw new Exception("没有指定数据表名");
        String sql="insert into "+key.getTableName()+"(";
        String valuesql="";
        List parmList=new ArrayList();
        for(int f=0;f<field.length;f++){
            String fname=field[f].getName();
            Class type=field[f].getType();
            if(!checkDataType(type))
                continue;

            Object obj=BeanUtils.getValue(bean, fname);
            if(fname.equalsIgnoreCase(key.getKeyCode())){
                //获取主键
                Object keyvalue=BeanUtils.getValue(bean, key.getKeyCode());
                if(keyvalue==null){
                    keyvalue=new Seq().getKeyId(key);
                    BeanUtils.setValue(bean, fname, keyvalue);
                }else if(keyvalue.toString().equals("-999"))
                    keyvalue=null;

                obj=keyvalue;
            }
            if(obj!=null){
                if(!valuesql.equals("")){
                    sql+=",";
                    valuesql+=",";
                }
                sql+=fname;
                valuesql+="?";
                obj=DataConversionFactory.getDataConversion(HibernateUtil.getDataBaseType(ftg)).valueToDbData(obj, type);
                parmList.add(obj);
            }
        }
        sql+=") values ("+valuesql+")";
        baseDao.execute2(sql, parmList);
    }
    public void update(TableBean bean) throws Exception{
        Field[] field=bean.getClass().getDeclaredFields();
        TableKey key=bean.getTableKey();
        if(key.getTableName()==null || "".equals(key.getTableName()))
            throw new Exception("没有指定数据表名");
        String sql="update "+key.getTableName();
        String setsql="";
        String keycol="";
        List parmlist=new ArrayList();
        for(int f=0;f<field.length;f++){
            String fname=field[f].getName();
            Class type=field[f].getType();
            if(!checkDataType(type))
                continue;
            if(!setsql.equals(""))
                setsql+=",";

            if(fname.equalsIgnoreCase(key.getKeyCode()))
                keycol=fname;
            else{
                setsql+=fname+" = ?";
                Object obj=BeanUtils.getValue(bean, fname);
                obj=DataConversionFactory.getDataConversion(HibernateUtil.getDataBaseType(ftg)).valueToDbData(obj, type);
                if(obj!=null && "".equals(obj.toString()))obj=null;
                parmlist.add(obj);
            }
        }
        sql+=" set "+setsql+" where "+keycol+" = ?";
        Object keyvalue=BeanUtils.getValue(bean, keycol);
        if(keycol.equals("") || keyvalue==null){
            throw new Exception("没有指定的主键!");
        }
        parmlist.add(keyvalue);
        baseDao.execute2(sql, parmlist);
    }
    public int update(String sql,Object[] obj) throws HibernateException, Exception{
        return baseDao.execute(sql, obj);
    }
    public int update(String tableName,Map updateMap,Map keyMap) throws HibernateException, Exception{
        return baseDao.update(tableName, updateMap, keyMap);
    }
    public void save(String tableName,Map dataMap) throws HibernateException, Exception{
        baseDao.save(tableName, dataMap);
    }
    public String saveReturnKey(String tableName,Map dataMap) throws  Exception{
        return baseDao.saveReturnKey(tableName, dataMap);
    }
    public void delete(TableBean bean) throws HibernateException, Exception{

    }
    public int delete(String sql,Object[] obj) throws HibernateException, Exception{
        return baseDao.execute(sql, obj);
    }

    public Session getSession() throws Exception{
//        return HibernateUtil.currentSession(ftg);
        return null;
    }
    public Connection getConnection() throws HibernateException, Exception{
        return null;
    }
    public PreparedStatement createPreparedStatement(String sql) throws HibernateException, SQLException, Exception{
        PreparedStatement ps=getConnection().prepareStatement(sql);
        addPreparedStatement(ps);
        return ps;
    }
    public PreparedStatement createPreparedStatement(String sql,int type) throws HibernateException, SQLException, Exception{
        PreparedStatement ps=getConnection().prepareStatement(sql,type);
        addPreparedStatement(ps);
        return ps;
    }
    public Statement createStatement() throws HibernateException, SQLException, Exception{
        Statement st=getConnection().createStatement();
        addStatement(st);
        return st;
    }
    private ResultSet getResultSet(PreparedStatement ps) throws HibernateException, SQLException, Exception{
        ResultSet rs=ps.executeQuery();
        addResultSet(rs);
        return rs;
    }
    private ResultSet getResultSet(Statement st,String sql) throws HibernateException, SQLException, Exception{
        ResultSet rs=st.executeQuery(sql);
        addResultSet(rs);
        return rs;
    }
    private void addPreparedStatement(PreparedStatement ps){
        if(preparedStatementList==null)
            preparedStatementList=new ArrayList<PreparedStatement>();
        preparedStatementList.add(ps);
    }
    private void addStatement(Statement st){
        if(statementList==null)
            statementList=new ArrayList<Statement>();
        statementList.add(st);
    }
    private void addResultSet(ResultSet rs){
        if(resultSetList==null)
            resultSetList=new ArrayList<ResultSet>();
        resultSetList.add(rs);
    }
    public void closeStatements(){
        if(preparedStatementList!=null){
            for(int i=0;i<preparedStatementList.size();i++){
                PreparedStatement ps=preparedStatementList.get(i);
                if(ps!=null)
                    try {
                        ps.close();
                    } catch (SQLException e1) {
                    }
            }
            preparedStatementList.clear();
        }

        if(statementList!=null){
            for(int i=0;i<statementList.size();i++){
                Statement st=statementList.get(i);
                if(st!=null)
                    try {
                        st.close();
                    } catch (SQLException e1) {
                    }
            }
            statementList.clear();
        }
    }
    public void closeSession() {
        // TODO Auto-generated method stub
        closeStatements();
        try{
//           HibernateUtil.closeSession(ftg);

        }catch(Exception e){
            e.printStackTrace();
        }
    }
    public void closeSession(boolean forcibly){
        closeStatements();
//        try{
//            if(forcibly)
//                HibernateUtil.closeSession(ftg);
//            else{
//                if(!getSession().getTransaction().isActive()){
////                	System.out.print("--closeSession");
//                    HibernateUtil.closeSession(ftg);
//                }
//            }
//        }catch(Exception e){
//            e.printStackTrace();
//        }
    }
    private boolean checkDataType(Class c){
        boolean bl=false;
        if(c==String.class || c == Character.class || c == char.class)
            bl=true;
        else if(c == Long.class || c == long.class || c == Short.class || c == short.class || c==Integer.class || c == int.class)
            bl=true;
        else if(c == Float.class || c == float.class || c == Double.class || c == double.class)
            bl=true;
        else if(c == char[].class)
            bl=true;
        else if(c == byte[].class)
            bl=true;
        else if(c == Date.class || c == java.util.Date.class)
            bl=true;
        return bl;
    }

    public void beginTransaction() {
        try {
            getSession().beginTransaction();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
    public Transaction getTransaction() throws Exception{
        return null;
    }

    public void commit(){
        try {
            getSession().getTransaction().commit();
        } catch (HibernateException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (Exception e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

    }
    public void rollback() throws SQLException{
        try {
            getSession().getTransaction().rollback();
        } catch (HibernateException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (Exception e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
    }
    public String getFtg() {
        return ftg;
    }
    public void setFtg(String ftg) {
        this.ftg = ftg;
    }
    public boolean isLoadLob() {
        return loadLob;
    }
    public void setLoadLob(boolean loadLob) {
        this.loadLob = loadLob;
    }

}
